// Copyright (c) 2021 Presto Labs Pte. Ltd.
// Author: daniel

#include "coin2/exchange/bitbank/api_util/auth_key.h"

#include <sstream>
#include <string>

#include <boost/algorithm/string/replace.hpp>

#include "coin2/base/time.h"
#include "coin2/exchange/base/api_util/api_signature.h"
#include "coin2/exchange/base/api_util/json_writer.h"
#include "coin2/exchange/base/api_util/nonce_manager.h"

auto BitbankBaseAuth::GetAuth(
    const std::string& query_str,
    const std::string& nonce,
    const std::string& secret_key) const -> std::string {
  return ApiSignatureUtil::GetSignatureByHexHmacSHA256(nonce + query_str, secret_key);
}

auto BitbankBaseAuth::GetHeaderSet(const std::string& query_str) -> const HeaderSet& {
  CHECK_THROW(!header_set_.empty()) << "Header set is empty";
  auto nonce = std::to_string(impl::NonceManager::Get());
  header_set_[0].second = GetAccessKey();
  header_set_[1].second = nonce;
  header_set_[2].second = GetAuth(query_str, nonce, GetSecretKey());
  return header_set_;
}

AsioHttpContext* BitbankRestAuth::CreateRequestByGetWithSignature(
    const std::string& address,
    UrlParamsBuilder* builder) {
  std::string query_string = builder->ComputeQueryString();
  CHECK_THROW(builder->ComputePostBody().empty()) << "It is GET Method, No Payload";
  std::string target = address;
  if (!query_string.empty()) {
    target += "?" + query_string;
  }
  auto ahc = AsioHttpContext::NewGet(host_, port_, bind_ip_, target, GetHeaderSet(target));
  ahc->keep_user_agent = true;

  return ahc;
}

AsioHttpContext* BitbankRestAuth::CreateRequestByPostWithSignature(
    const std::string& address,
    UrlParamsBuilder* builder) {
  std::string query_string = builder->ComputeQueryString();
  std::string post_body = ComputeBitbankPostBody(builder);
  std::string target = address;
  if (!query_string.empty()) {
    target += "?" + query_string;
  }
  auto ahc =
      AsioHttpContext::NewPost(host_, port_, bind_ip_, target, GetHeaderSet(post_body), post_body);
  ahc->keep_user_agent = true;

  return ahc;
}

std::string BitbankRestAuth::ComputeBitbankPostBody(UrlParamsBuilder* builder) {
  std::string post_body = builder->ComputePostBody();
  // True/False cannot have quotes
  boost::replace_all(post_body, R"("True")", "true");
  boost::replace_all(post_body, R"("true")", "true");
  boost::replace_all(post_body, R"("False")", "false");
  boost::replace_all(post_body, R"("false")", "false");
  return post_body;
}
